import sys
import os
import FileManager
from PyQt4 import QtGui, QtCore

RUNLEVELS = 7

class MainWidget(QtGui.QWidget):
    def __init__(self):
        super(MainWidget, self).__init__()

        self.currentTab = 0
        self.addScriptButton = QtGui.QPushButton('Add', self)
        self.removeScriptButton = QtGui.QPushButton('Remove', self)
        self.moveStopToStartScriptButton = QtGui.QPushButton('Stop->Start', self)
        self.connect(self.moveStopToStartScriptButton, QtCore.SIGNAL('clicked()'), self.moveStopToStart)
        
        self.moveStartToStopScriptButton = QtGui.QPushButton('Start->Stop', self)
        self.connect(self.moveStartToStopScriptButton, QtCore.SIGNAL('clicked()'), self.moveStartToStop)
        
        self.stopUpButton = QtGui.QPushButton('stop up', self)
        self.connect(self.stopUpButton, QtCore.SIGNAL('clicked()'), self.stopUp)
        
        self.stopDownButton = QtGui.QPushButton('stop down', self)
        self.connect(self.stopDownButton, QtCore.SIGNAL('clicked()'), self.stopDown)
        
        self.startUpButton = QtGui.QPushButton('start up', self)
        self.connect(self.startUpButton, QtCore.SIGNAL('clicked()'), self.startUp)
        
        self.startDownButton = QtGui.QPushButton('start down', self)
        self.connect(self.startDownButton, QtCore.SIGNAL('clicked()'), self.startDown)
        
        self.saveScriptButton = QtGui.QPushButton('Save', self)
        self.reloadScriptButton = QtGui.QPushButton('Reload', self)
        
        self.exitButton = QtGui.QPushButton('Exit', self)
        self.connect(self.exitButton, QtCore.SIGNAL('clicked()'), QtCore.SLOT('close()'))
        
        self.createScriptButton = QtGui.QPushButton('Create script for application', self)
        self.fullScriptPathLabel = QtGui.QLabel(self)
        self.scriptEditor = QtGui.QTextEdit(self)
        self.runlevelStartLists = []
        self.runlevelStopLists = []
        self.currentListItem = None
        self.isDirty = False
        self.fileManager = FileManager.FileManager(RUNLEVELS)      
        self.scriptEditor.setAcceptRichText(False)    
        self.scriptEditor.installEventFilter(self)
        
        for _ in range(0, RUNLEVELS):
            self.runlevelStopLists.append(QtGui.QListWidget())  
            self.runlevelStartLists.append(QtGui.QListWidget()) 

        self.initUI()
        self.initLists()      
        
    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            if self.currentListItem != None and not self.isDirty:
                self.currentListItem.setText(self.currentListItem.text() + "*")
                self.isDirty = True
        return QtGui.QTextEdit.eventFilter(self, watched, event)

    
    def moveStopToStart(self):
        self.moveBetweenLists(self.runlevelStopLists,self.runlevelStartLists,'K','S')
    
    def moveStartToStop(self):
        self.moveBetweenLists(self.runlevelStartLists,self.runlevelStopLists,'S','K')
        
    def moveBetweenLists(self, sourceList, destinationList, sourceRunSign, destinationRunSign):
        index = self.tabWidget.currentIndex()
        
        # from empty even Salomon won't fill xD
        if(sourceList[index].count() == 0):
            return
        
        currentRow = sourceList[index].currentRow()
        currentItem = sourceList[index].takeItem(currentRow)
        currentItemPriority = int(str(currentItem.text()).split(':')[0])
        
        currentItemPriorityStr = str(currentItemPriority)
        if(currentItemPriority < 10):
            currentItemPriorityStr = '0' + currentItemPriorityStr
        
        script = str(currentItem.text()).split(':')[1]
        oldSymbolicLink = '/etc/rc'+str(index)+'.d/'+sourceRunSign+currentItemPriorityStr+script[1:]
        newSymbolicLink = '/etc/rc'+str(index)+'.d/'+destinationRunSign+currentItemPriorityStr+script[1:]
        os.system('mv ' + oldSymbolicLink + ' ' + newSymbolicLink)
        
        destinationListSize = destinationList[index].count()
        # destination list is empty, insert at the beggining
        if(destinationListSize == 0):
            destinationList[index].insertItem(0, currentItem)
            return
            
        # insert item in a sorted by priority way
        for row in range(0,destinationListSize):
            desinationItem = destinationList[index].item(row)
            destinationItemPriority = int(str(desinationItem.text()).split(':')[0])
            if(currentItemPriority <= destinationItemPriority):
                destinationList[index].insertItem(row, currentItem)
                return;
                
        # if we got so far, insert at the end
        destinationList[index].insertItem(destinationListSize, currentItem)
    
    def stopDown(self):
        self.goThroughList(self.runlevelStopLists,'K',1)     
    
    def startDown(self):
        self.goThroughList(self.runlevelStartLists,'S',1)

    def stopUp(self):
        self.goThroughList(self.runlevelStopLists,'K',-1)

    def startUp(self):
        self.goThroughList(self.runlevelStartLists,'S',-1)
       
    def goThroughList(self,runLevelList, runSign, additionPart):
        index = self.tabWidget.currentIndex()
        currentRow = runLevelList[index].currentRow()
    
        currentItem = runLevelList[index].takeItem(currentRow)
        currentItemPriority = int(str(currentItem.text()).split(':')[0])
        newCurrentItemPriority = currentItemPriority + additionPart
        script = str(currentItem.text()).split(':')[1]
        
        # priority can be only between 1 and 99
        if(newCurrentItemPriority < 1):
            newCurrentItemPriority = 1
        if(newCurrentItemPriority > 99):
            newCurrentItemPriority = 99
   
        if(currentItemPriority != newCurrentItemPriority):
            currentItem.setText(str(newCurrentItemPriority) + ':' + script)
            
			# if we go down and try to switch last but one item with last item
            if(additionPart == 1 and currentRow == runLevelList[index].count()-1):
                lastItem = runLevelList[index].item(currentRow)
                lastItemPriority = int(str(lastItem.text()).split(':')[0])
                
                if(newCurrentItemPriority > lastItemPriority):
                    runLevelList[index].insertItem(runLevelList[index].count(), currentItem)
            
            if((additionPart == -1 and currentRow > 0) or (additionPart == 1 and currentRow < (runLevelList[index].count()-1))):                
                neighbourItem = runLevelList[index].item(currentRow + additionPart)
                neighbourItemPriority = int(str(neighbourItem.text()).split(':')[0])            
                row = currentRow + additionPart
                flag = 0
                
                # try to find right place in sorted list depending on moving up or down
                while((additionPart == -1 and row > 0 and neighbourItemPriority > newCurrentItemPriority) or (additionPart == 1 and row < (runLevelList[index].count()-1) and neighbourItemPriority < newCurrentItemPriority)):
                    flag = 1
                    neighbourItem = runLevelList[index].item(row)
                    neighbourItemPriority = int(str(neighbourItem.text()).split(':')[0]) 
                    row = row + additionPart   
                                
                # if the right place was found insert there an item
                if(flag==1):
                    addition = 0
                    
                    if(additionPart == -1):
                        addition = 2*additionPart
                    else:
                        addition = additionPart
                
                    runLevelList[index].insertItem(row - addition, currentItem)             
                else:
                    runLevelList[index].insertItem(currentRow, currentItem)
            else:
                runLevelList[index].insertItem(currentRow, currentItem)
                
            # adjust string priority and perform files operations
            currentItemPriorityStr = str(currentItemPriority)
            if(currentItemPriority < 10):
                currentItemPriorityStr = '0' + currentItemPriorityStr
                
            newItemPriorityStr = str(newCurrentItemPriority)
            if(newCurrentItemPriority < 10):
                newItemPriorityStr = '0' + newItemPriorityStr
                
            oldSymbolicLink = '/etc/rc'+str(index)+'.d/'+runSign+currentItemPriorityStr+script[1:]
            newSymbolicLink = '/etc/rc'+str(index)+'.d/'+runSign+newItemPriorityStr+script[1:]
            os.system('mv ' + oldSymbolicLink + ' ' + newSymbolicLink)
        else:
            # insert item in the same place
            runLevelList[index].insertItem(currentRow, currentItem)
                
        
    def initUI(self):
        mainLayout = QtGui.QVBoxLayout()
        leftLayout = QtGui.QVBoxLayout()
        leftBottomLayout = QtGui.QVBoxLayout()
        rightLayout = QtGui.QVBoxLayout()
        rightBottomLayout = QtGui.QHBoxLayout()      
       
        selectScriptLabel = QtGui.QLabel('Select script', self)      
        selectScriptLabel.setAlignment(QtCore.Qt.AlignCenter)
             
        editScriptLabel = QtGui.QLabel('Edit script', self)
        editScriptLabel.setAlignment(QtCore.Qt.AlignCenter)
        
        self.resize(700, 600)
        self.setWindowTitle('Runlevels configuration editor')

        leftBottomLayoutUp = QtGui.QHBoxLayout()
        leftBottomLayoutUp.addWidget(self.addScriptButton)
        leftBottomLayoutUp.addWidget(self.removeScriptButton)
        leftBottomLayoutUp.addWidget(self.moveStopToStartScriptButton)    
        leftBottomLayoutUp.addWidget(self.moveStartToStopScriptButton)  
        
        leftBottomLayoutDown = QtGui.QHBoxLayout()
        leftBottomLayoutDown.addWidget(self.stopUpButton)
        leftBottomLayoutDown.addWidget(self.stopDownButton)
        leftBottomLayoutDown.addWidget(self.startUpButton)
        leftBottomLayoutDown.addWidget(self.startDownButton)
        
        leftBottomLayout.addLayout(leftBottomLayoutUp)
        leftBottomLayout.addLayout(leftBottomLayoutDown)
        
        rightBottomLayout.addSpacerItem(QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Expanding))
        rightBottomLayout.addWidget(self.saveScriptButton)
        rightBottomLayout.addWidget(self.reloadScriptButton)
        rightBottomLayout.addWidget(self.createScriptButton)
        rightBottomLayout.addSpacerItem(QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Expanding))

        self.tabWidget = QtGui.QTabWidget()
        self.tabWidget.setParent(self)
        self.tabWidget.setMaximumWidth(300)
        self.tabWidget.setTabPosition(QtGui.QTabWidget.West)
        self.tabWidget.currentChanged.connect(self.clearSelection)
        
        for i in range(0, RUNLEVELS):      
            page = QtGui.QWidget()
            listStartWidget = self.runlevelStartLists[i]
            listStartWidget.setParent(page)
            listStopWidget = self.runlevelStopLists[i]
            listStopWidget.setParent(page)
            pageLayout = QtGui.QVBoxLayout()
            
            stopLabel = QtGui.QLabel('Stop:', self)             
            pageLayout.addWidget(stopLabel)
            pageLayout.addWidget(listStopWidget)
            
            startLabel = QtGui.QLabel('Start:', self)
            pageLayout.addWidget(startLabel)
            pageLayout.addWidget(listStartWidget)
            page.setLayout(pageLayout)
            self.tabWidget.addTab(page, 'Runlevel ' + str(i))
            listStartWidget.itemActivated.connect(self.displayScript)
            listStopWidget.itemActivated.connect(self.displayScript)


        leftLayout.addWidget(selectScriptLabel)
        leftLayout.addWidget(self.tabWidget)
        leftLayout.addLayout(leftBottomLayout)
        rightLayout.addWidget(editScriptLabel)
        rightLayout.addWidget(self.fullScriptPathLabel)
        rightLayout.addWidget(self.scriptEditor)
        rightLayout.addLayout(rightBottomLayout)
        leftRightLayout = QtGui.QHBoxLayout()
        leftRightLayout.addLayout(leftLayout)
        leftRightLayout.addLayout(rightLayout)
        mainLayout.addLayout(leftRightLayout)
        exitLayout = QtGui.QHBoxLayout()
        exitLayout.setAlignment(QtCore.Qt.AlignRight)
        exitLayout.addWidget(self.exitButton)
        mainLayout.addLayout(exitLayout)

        self.setLayout(mainLayout)
        self.show()

    def initLists(self):
        for i in range(0, RUNLEVELS):
            stopEntries = self.fileManager.stopEntries(i)
            for num, label in stopEntries:
                self.runlevelStopLists[i].addItem(str(num) + ": " + label)
            startEntries = self.fileManager.startEntries(i)
            for num, label in startEntries:
                self.runlevelStartLists[i].addItem(str(num) + ": " +label)

    def displayScript(self, listItem):
        if self.isDirty and not self.askDiscard():
            return
            
        
        if self.currentListItem != None and self.isDirty:
            self.currentListItem.setText(self.currentListItem.text()[:-1])
            self.isDirty = False
        
        scriptName = listItem.text().split(": ")[1]
        self.fullScriptPathLabel.setText(self.fileManager.getFilePath(scriptName))
        self.scriptEditor.setPlainText(self.fileManager.getFileContents(scriptName))
       
        
        self.currentListItem = listItem

    def clearScriptDisplay(self):
        self.scriptEditor.clear()
        
    def clearSelection(self, newTab):
        if self.isDirty and not self.askDiscard():
            return
        
        self.runlevelStartLists[self.currentTab].setCurrentRow(-1)
        self.runlevelStopLists[self.currentTab].setCurrentRow(-1)
        self.clearScriptDisplay()
        self.currentTab = newTab
        if (self.currentListItem != None):
            self.currentListItem.setText(self.currentListItem.text()[:-1])
            
    def askDiscard(self):
        reply = QtGui.QMessageBox.warning(self, 'Warning', "Are you sure you want to discard changes?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
        return reply == QtGui.QMessageBox.Yes

def main():
    app = QtGui.QApplication(sys.argv)
    ex = MainWidget()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()    